#include "config.h"
#include "delay.h"
#include "./Driver/74HC165.h"
#include "./Driver/74HC595.h"
#include "./Driver/AS62.h"
#include "./Driver/C50XB.h"
#include "./HALayer/Tim.h"
#include "./HALayer/LED.h"
#include "./HALayer/Key.h"
#include "./App/AGV_CMD.h"
#include <stm32f0xx_rcc.h>
#include <stm32f0xx_pwr.h>
#include <stm32f0xx_adc.h>

extern "C" void TIM3_IRQHandler(void);
extern "C" void TIM16_IRQHandler(void);

enum
{
	Control_AGV,	//和AGV通信
	Control_Center	//和物料中心通信
}Wireless_Call_Mode;	//无线呼叫模式


HC595_Class Indicateor;	//74HC595端口上的指示灯、蜂鸣器和C50XB的设置、休眠引脚
HC165_Class DIP_SW;		//74HC165端口上的拨码开关和按键

IO WTD = IO(GPIOA, GPIO_Pin_0);	//看门狗

WirelessSerial_Class *My_Serial;	//指向当前无线串口设备的指针
AS62_Class AS62_Wireless_Module;	//AS62无线串口模块
C50XB_Class C50XB_Wireless_Module;	//C50XB无线串口模块

uint32_t baudrate = DEFAULT_BAUDRATE;	//默认波特率
bool _tim_flag = 0;	//用于表示时间基准（50ms）时间是否已经达到

LED Call_R, Call_B, Back_R, Back_B, PW_LED, Buzzer;	//呼叫红蓝灯、放行红蓝灯,模块片选、电源脚、蜂鸣器
KEY Call, Back;
AGV_CMD_Class Call_Center_AGV, Back_Center_AGV, Back_AGV;	//向物料中心或AGV呼叫，向物料中心或AGV放行，向AGV放行
AGV_CMD_Class *Cmd_Current = &Call_Center_AGV;	//当前指令

uint8_t AGV_ADD = 0;	//AGV小车呼叫地址
uint8_t Subcode = 0;	//呼叫盒站点

bool task_current_flag = false;	//true表示当前有任务
bool task_back = false;	//true表示向物料中心发送的放行任务已经结束
Indic indic_back_center = NO_Indic;	//向物料中心放行的指示暂存

bool set_or_work = false;	//false表示设置模式，true表示工作模式

uint16_t adc_value = 0, led_cnt = 100;

uint16_t Init_System(void);	//初始化系统与外设，返回74HC165的值
void Init_System_RCC(void);
void Init_System_TIM(void);
void Update_Indicateor(void);	//更新74HC595端口的输出电平

void Init_ADC(void);	//ADC软件触发采样

void Work_Function(void);	//工作模式函数
void Set_Function(void);	//设置模式函数

int main(void)
{
	set_or_work = (bool)(Init_System() & 0x0FFF);	//初始化系统外设，返回74HC165端口锁存值
	PW_LED.flag = true;
	My_Serial->Mode(WirelessSerial_Class::Normal, true);
	My_Serial->Mode(WirelessSerial_Class::Set_Mode, true);
	//My_Serial->Set_State(true);
	Update_Indicateor();
	delay_ms(1000);
	delay_ms(1000);	//等待无线模块进入设置状态


#ifdef POST
	if (!My_Serial->Parameter(WirelessSerial_Class::READ))	//读取参数失败
	//if (!My_Serial->Read_Parameter(baudrate))//读取参数
	{
		Buzzer.flag = true;	//自检失败，蜂鸣器长响，不工作
		Update_Indicateor();
		while (1)
		{
		}
	}
	if (set_or_work)
	{
		baudrate = My_Serial->Return_Baudrate();	//获取波特率
		My_Serial->Init(baudrate);
		Work_Function();
	}
	else
	{
		Set_Function();
	}
#else
	if (set_or_work)
	{
		My_Serial->Init(115200);
		Work_Function();
	}
	else
	{
		Set_Function();
	}
#endif // POST

}


//************************************
// Method:    Init_System
// FullName:  Init_System
// Access:    public 
// Returns:   uint16_t 返回74HC165的值
// Parameter: void
// Description:	初始化系统外设以及外部ic和模块
//************************************
uint16_t Init_System(void)
{
	uint16_t dip_sw_temp = 0;
	delay_init();
	Init_System_RCC();
	WTD.Init(GPIO_Mode_OUT);
	Init_ADC();
	Indicateor.Init();
	DIP_SW.Init();
	RCC->AHBENR &= ~RCC_AHBPeriph_GPIOB;	//关闭GPIOB时钟（74HC595的OE脚，降低功耗）

	dip_sw_temp = DIP_SW.Read(16);

	AGV_ADD = (dip_sw_temp & 0x0F00) >> 8;
	Subcode = dip_sw_temp & 0x00FF;

	switch ((dip_sw_temp >> 12) & 0x01)	//bit12-2Pin拨码开关2位,0 - 使用C50XB模块，1 - 使用E32-TTL模块
	{
	case 0x00:	//使用C50XB 433Mhz模块
		My_Serial = &C50XB_Wireless_Module;
		break;
	case 0x01:	//使用AS62-TTL-1W模块
		My_Serial = &AS62_Wireless_Module;
		break;
	default:	//缺省设置使用C50XB 433Mhz模块
		My_Serial = &C50XB_Wireless_Module;
		break;
	}

	switch ((dip_sw_temp >> 13) & 0x01)	//bit13-2Pin拨码开关1位,0 - 和AGV通信，1 - 和物料中心通信
	{
	case 0x00:
		Wireless_Call_Mode = Control_AGV;	//和AGV通信
		break;
	case 0x01:
		Wireless_Call_Mode = Control_Center;	//和物料中心通信
		break;
	default:
		Wireless_Call_Mode = Control_AGV;	//缺省设置和AGV通信
		break;
	}

	switch (Wireless_Call_Mode)
	{
	case Control_AGV:
		Call_Center_AGV.Init(AGV_Frame_Head, AGV_ADD, 0x09, Subcode);
		Back_Center_AGV.Init(AGV_Frame_Head, AGV_ADD, 0x08, Subcode);
		Back_AGV.Init(AGV_Frame_Head, AGV_ADD, 0x08, Subcode);
		break;
	case Control_Center:
		Call_Center_AGV.Init(Centre_Frame_Head, AGV_ADD, 0x09, Subcode);
		Back_Center_AGV.Init(Centre_Frame_Head, AGV_ADD, 0x08, Subcode);
		Back_AGV.Init(AGV_Frame_Head, AGV_ADD, 0x08, Subcode);
		break;
	default:
		break;
	}

	Init_System_TIM();
	Time_Open(TIM16);	//打开定时器16

	My_Serial->Init(baudrate);
	return dip_sw_temp;
}

//打开stm32外设时钟：GPIOA、GPIOB、UART1、ADC1、TIM3、TIM14、TIM16
void Init_System_RCC(void)
{
	RCC->AHBENR |= (RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB);	//打开GPIOA、GPIOB时钟
	RCC->APB1ENR |= (RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM14);	//打开TIM3、TIM14
	RCC->APB2ENR |= (RCC_APB2Periph_ADC1 | RCC_APB2Periph_TIM16 | RCC_APB2Periph_USART1);	//打开UART1、ADC1、TIM16
}

void Init_System_TIM(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	//uint16_t TIM14_Arr = 0;	//TIM14重装值（用于检测Modbus）


	Init_Time(TIM3, 4000, 100);	//设置定时器3的中断频率20Hz，时基定时器

	//TIM14_Arr = (uint16_t)(SystemCoreClock / (baudrate / 22) / 10 + 1);	//设置静默时间为22个位(定时器分频系数10)
	//Init_Time(TIM14, TIM14_Arr, 10);//设置定时器14的中断频率，用于设置串口Modbus检测超时
	Init_Time(TIM16, 8000, 10);	//设置定时器16的中断频率是100Hz，用于按键检测，电量指示

	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPriority = 4;
	NVIC_Init(&NVIC_InitStructure);

	//NVIC_InitStructure.NVIC_IRQChannel = TIM14_IRQn;
	//NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	//NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
	//NVIC_Init(&NVIC_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = TIM16_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPriority = 3;
	NVIC_Init(&NVIC_InitStructure);


}

void Update_Indicateor(void)
{
	Indicateor.HC595_Value.Uart_Set0 = !My_Serial->WF_Set0;	//硬件电路反向
	Indicateor.HC595_Value.Uart_Set1 = !My_Serial->WF_Set1;	//硬件电路反向
	Indicateor.HC595_Value.Back_B = Back_B.flag;
	Indicateor.HC595_Value.Back_R = Back_R.flag;
	Indicateor.HC595_Value.Buzzer = Buzzer.flag;
	Indicateor.HC595_Value.Call_B = Call_B.flag;
	Indicateor.HC595_Value.Call_R = Call_R.flag;
	Indicateor.HC595_Value.Power_LED = PW_LED.flag;

	Indicateor.Write();
}

void Init_ADC(void)
{
	ADC_InitTypeDef ADC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	ADC_DeInit(ADC1);

	ADC_StructInit(&ADC_InitStructure);
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
	ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
	ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
	ADC_Init(ADC1, &ADC_InitStructure);

	ADC_OverrunModeCmd(ADC1, ENABLE);
	ADC_ChannelConfig(ADC1, ADC_Channel_1, ADC_SampleTime_239_5Cycles);
	ADC_GetCalibrationFactor(ADC1);
	ADC_Cmd(ADC1, ENABLE);
	while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY));

}

void Work_Function(void)
{
	Init_System_TIM();	//根据新的波特率更新接收超时时间
	Time_Open(TIM16);	//打开定时器16
	Time_Open(TIM3);	//打开定时器3

						//My_Serial->Set_State(false);	//无线模块退出设置状态
						//My_Serial->Sleep(false);		//无线模块退出休眠状态
						//Update_Indicateor();

	for (int i = 0; i < 6; i++)
	{
		Buzzer.flag = !Buzzer.flag;
		PW_LED.flag = 1;
		Update_Indicateor();
		delay_ms(200);
	}
	My_Serial->Mode(WirelessSerial_Class::Normal, true);
	//My_Serial->Set_State(false);	//无线模块退出设置状态
	//My_Serial->Sleep(false);		//无线模块退出休眠状态
	Update_Indicateor();
	Call.pb = 0;
	Back.pb = 0;

	while (1)
	{
		//My_Serial->Send("hello \r\n");
		//Indicateor.HC595_Value.Power_LED = !Indicateor.HC595_Value.Power_LED;
		//Indicateor.Write();
		//delay_ms(200);

		if (My_Serial->Return_rx_flag())	//接收到了一帧数据
		{
			Cmd_Current->find_cmd(My_Serial->Return_RX_buf(), My_Serial->Return_rx_cnt());	//检查指令应答
			My_Serial->Clear_rx_flag();
			My_Serial->Clear_rx_cnt();
		}

		task_current_flag = Call_Center_AGV.TX_Flag() || Back_Center_AGV.TX_Flag() || Back_AGV.TX_Flag();
		if (task_current_flag)	//当前有发送任务
		{
			Call.pb = 0;
			Back.pb = 0;

			My_Serial->Mode(WirelessSerial_Class::Normal, true);
			//My_Serial->Sleep(false);
		}
		else
		{
			My_Serial->Mode(WirelessSerial_Class::Sleep_Mode, true);
			//My_Serial->Sleep(true);
		}


		if (Call.pb)
		{
			Call_Center_AGV.Set_TX();
			Call.pb = 0;
			Cmd_Current = &Call_Center_AGV;
		}
		else if (Back.pb)
		{
			Back_Center_AGV.Set_TX();
			Back.pb = 0;
			Cmd_Current = &Back_Center_AGV;
		}

		if (_tim_flag == 1)	//50ms时基到
		{
			static char *str = 0;
			static int length = 0;
			_tim_flag = 0;
			length = Cmd_Current->Check(str);	//获取指令
			if (length)
			{
				My_Serial->print(str, length);
			}


			Buzzer.Check();
			Call_B.Check();
			Call_R.Check();
			Back_B.Check();
			Back_R.Check();

			//#ifdef CENTER
			if (Wireless_Call_Mode == Control_Center)
			{
				if (task_back)
				{
					Back_AGV.Set_TX();
					Cmd_Current = &Back_AGV;
					task_back = false;
				}
			}

			//#endif // CENTER

		}

		if ((Back_Center_AGV.tx_state == AGV_CMD_Class::SUCCESS_ACK) || (Back_Center_AGV.tx_state == AGV_CMD_Class::ERROR_ACK))
		{
			task_back = true;
		}


		switch (Call_Center_AGV.indic)
		{
		case NO_Indic:
			break;
		case SENDING_Indic:
			Buzzer.cnt = BEEP_SHORT_TIME;
			break;
		case RIGHT_Indic:
			Call_B.cnt = LED_TIME;
			break;
		case BUSY_Indic:
			Call_B.cnt = LED_TIME;
			Call_R.cnt = LED_TIME;
			break;
		case FAILURE_Indic:
			Call_R.cnt = LED_TIME;
			break;
		default:
			break;
		}

		//#ifdef CENTER
		if (Wireless_Call_Mode == Control_Center)
		{
			if ((Back_Center_AGV.indic == SENDING_Indic) || (Back_AGV.indic == SENDING_Indic))
			{
				Buzzer.cnt = BEEP_SHORT_TIME;
			}

			if ((Back_Center_AGV.indic == RIGHT_Indic) || (Back_Center_AGV.indic == FAILURE_Indic))
			{
				indic_back_center = Back_Center_AGV.indic;
			}
			if ((indic_back_center == RIGHT_Indic) && (Back_AGV.indic == RIGHT_Indic))
			{
				Back_B.cnt = LED_TIME;
				indic_back_center = NO_Indic;
			}
			else if ((Back_AGV.indic == FAILURE_Indic) || (Back_AGV.indic == RIGHT_Indic))
			{
				Back_R.cnt = LED_TIME;
			}
		}
		//#else
		else
		{
			switch (Back_Center_AGV.indic)
			{
			case NO_Indic:
				break;
			case SENDING_Indic:
				Buzzer.cnt = BEEP_SHORT_TIME;
				break;
			case RIGHT_Indic:
				Back_B.cnt = LED_TIME;
				break;
			case BUSY_Indic:
				Back_B.cnt = LED_TIME;
				Back_R.cnt = LED_TIME;
				break;
			case FAILURE_Indic:
				Back_R.cnt = LED_TIME;
				break;
			default:
				break;
			}
		}
		//#endif // CENTER

		Call_Center_AGV.indic = NO_Indic;
		Back_Center_AGV.indic = NO_Indic;
		Back_AGV.indic = NO_Indic;

		Update_Indicateor();	//更新指示

		PWR_EnterSleepMode(PWR_SLEEPEntry_WFI);
	}
}

void Set_Function(void)
{

	enum WirelessSerial_Class::SET_WF_Property Property;	//设置的属性
	uint8_t value;	//设置的值

	uint16_t dip_sw_temp = 0;	//拨码开关暂存

	Time_Open(TIM16);	//打开定时器16
	Buzzer.flag = true;
	Update_Indicateor();
	delay_ms(1000);
	Buzzer.flag = false;
	Update_Indicateor();

	//Time_Open(TIM3);	//打开定时器3

	while (1)
	{
		if (Call.pb)	//检测到按键
		{
			dip_sw_temp = DIP_SW.Read(16) & 0x0FFF;

			Property = (WirelessSerial_Class::SET_WF_Property)((dip_sw_temp & 0x0F00) >> 8);
			value = dip_sw_temp & 0x00FF;

			switch (Property)
			{
			case WirelessSerial_Class::SET_BAUDRATE:	//设置波特率
				My_Serial->baudrate_level = value;
				break;
			case WirelessSerial_Class::SET_WF_RATE:	//设置无线速率
				My_Serial->wfrate_level = value;
				break;
			case WirelessSerial_Class::SET_CHANNEL:	//设置信道
				if (value >= 1 && value <= 40)
				{
					My_Serial->channel = value;
				}
				break;
			case WirelessSerial_Class::SET_FEC:	//设置FEC开关
				My_Serial->open_FEC = value ? true: false;	//设置FEC打开或者关闭
				break;
			default:
				break;
			}	 //设置相应属性

			Buzzer.flag = true;
			Update_Indicateor();
			delay_ms(50);
			Buzzer.flag = false;
			Update_Indicateor();

			Call.pb = false;
		}

		if (Back.pb)
		{
			My_Serial->Parameter(WirelessSerial_Class::SET);
			//My_Serial->Set_Parameter();
			Buzzer.flag = true;
			Update_Indicateor();
			delay_ms(200);
			Buzzer.flag = false;
			Update_Indicateor();
			Back.pb = false;
		}
	}
}


////串口1		工作在发送接收模式，中断优先级2
//void USART1_IRQHandler(void)
//{
//	if (USART1->ISR&(1 << 5))	//接受中断
//	{
//		TIM14->CNT = 0;	//计数器清0
//		TIM14->CR1 |= TIM_CR1_CEN;	//使能定时器1
//		My_Serial->Write(USART1->RDR);
//	}
//}


//定时器3	用于等待应答超时检测，亮灯、蜂鸣器时间判断, 中断优先级4，中断频率20Hz
void TIM3_IRQHandler(void)
{
	static uint16_t _tim3_cnt = 0;
	if (TIM3->SR&TIM_IT_Update)	//更新中断
	{
		TIM3->SR = ~TIM_IT_Update;
		_tim_flag = true;

		_tim3_cnt++;
		if ((_tim3_cnt % 5) == 0)
		{
			adc_value = (ADC1->DR) >> 4;
			ADC1->CR |= ADC_CR_ADSTART;
		}

		led_cnt++;
		if (led_cnt > 150)
		{
			led_cnt = 100;
		}
		if (led_cnt > adc_value)
		{
			PW_LED.flag = 0;
		}
		else
		{
			PW_LED.flag = 1;
		}
	}
}

////定时器14	用于串口Modbus检测，中断优先级1
//void TIM14_IRQHandler(void)
//{
//	if (TIM14->SR&TIM_IT_Update)	//更新中断
//	{
//		TIM14->SR = ~TIM_IT_Update;
//		TIM14->CR1 &= ~TIM_CR1_CEN;	//关闭定时器14
//		My_Serial->rx_frame_flag = true;//接受到了一帧数据
//	}
//}

//定时器16	用于按键扫描，看门狗喂狗, 电量指示灯，中断优先级3，中断频率100Hz
void TIM16_IRQHandler(void)
{
	static uint16_t key_value = 0;
	static uint16_t _tim16_cnt = 0;
	if (TIM16->SR&TIM_IT_Update)	//更新中断
	{
		key_value = DIP_SW.Read(2);	//读取两个按键状态
		Call.Scan(key_value & 0x01);
		Back.Scan(key_value >> 1);

		if ((_tim16_cnt % 5) == 0)
		{
			WTD.Toggle();	//喂狗
		}
		_tim16_cnt++;
		TIM16->SR = ~TIM_IT_Update;
	}
}